﻿// 2025/10/14: 首个版本
// 2025/10/15: 改为继承Panel
// 2025/11/12: 使用menu-item样式。修正鼠标拖拽异常

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using Avalonia.Controls;
using Avalonia.Media;
using Avalonia.Platform.Storage;
using SkiaSharp;
using ASEva;
using ASEva.UIAvalonia;

namespace CommonSource
{
    partial class DebuggerPanel : Panel
    {
        public DebuggerPanel()
        {
            InitializeComponent();
            language = new LanguageSwitch(Resources, AgencyLocal.GetAppLanguage());

            itemClear.Click += delegate
            {
                Clear();
            };

            itemAutoScroll.IsCheckedChanged += delegate
            {
                autoScroll = itemAutoScroll.IsChecked.Value;
            };

            itemExport.Click += async delegate
            {
                if (ExportRequest != null)
                {
                    ExportRequest(this, null);
                    return;
                }

                var selected = await this.GetStorageProvider().SaveFilePickerAsync(new FilePickerSaveOptions
                {
                    Title = language["dialog-title"],
                    FileTypeChoices = [new FilePickerFileType(language["suffix"]) { Patterns = ["*.txt"] }]
                });
                if (selected != null) ExportMessages(selected.Path.LocalPath);
            };

            PointerPressed += (o, e) =>
            {
                if (e.ClickCount == 2) itemAutoScroll.IsChecked = !itemAutoScroll.IsChecked;
            };

            PointerMoved += (o, e) =>
            {
                lock (bufferTable)
                {
                    if (!bufferTable.ContainsKey(id)) return;
                }
                if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
                {
                    itemAutoScroll.IsChecked = false;
                    target = (int)((float)e.GetCurrentPoint(this).Position.Y / Bounds.Height * bufferTable[id].Count);
                }
            };

            PointerWheelChanged += (o, e) =>
            {
                itemAutoScroll.IsChecked = false;
                if (e.Delta.Y > 0) target--;
                else target++;
                if (target < 0) target = 0;
            };

            skiaView.RenderSkia += (o, e) =>
            {
                try { doPaint(e.Canvas); }
                catch (Exception) { }
            };
        }

        public String ModuleID { set => skiaView.ModuleID = value; }

        public void QueueRender() => skiaView.QueueRender();

        public void Clear()
        {
            if (bufferTable.ContainsKey(id))
            {
                bufferTable[id].Clear();
                target = -1;
            }
        }

        public void InputMessage(String msg, String id)
        {
            var rows = msg.Replace("\r\n", "\n").Split('\n');
            var okMsgs = new List<string>();
            foreach (var row in rows)
            {
                if (row.Length == 0) continue;
                okMsgs.Add(row.Replace("\t", "    "));
            }

            if (bufferTable.ContainsKey(id))
            {
                var targetBuffer = bufferTable[id];
                targetBuffer.AddRange(okMsgs);
                if (targetBuffer.Count > 11000)
                {
                    targetBuffer.RemoveRange(0, 1000);
                    if (this.id == id) target -= 1000;
                }
            }
            else bufferTable[id] = okMsgs.ToList();
        }

        public void InputMessages(Dictionary<String, List<String>> msgTable)
        {
            foreach (var pair in msgTable)
            {
                var id = pair.Key;
                var msgs = pair.Value;

                var okMsgs = new List<string>();
                foreach (var msg in msgs)
                {
                    var rows = msg.Replace("\r\n", "\n").Split('\n');
                    foreach (var row in rows)
                    {
                        if (row.Length == 0) continue;
                        okMsgs.Add(row.Replace("\t", "    "));
                    }
                }

                if (bufferTable.ContainsKey(id))
                {
                    var targetBuffer = bufferTable[id];
                    targetBuffer.AddRange(okMsgs);
                    if (targetBuffer.Count > 11000)
                    {
                        targetBuffer.RemoveRange(0, 1000);
                        if (this.id == id) target -= 1000;
                    }
                }
                else bufferTable[id] = okMsgs.ToList();
            }
        }

        public String[] GetIDList()
        {
            return bufferTable.Keys.ToArray();
        }

        public Dictionary<String, int> GetCountTable()
        {
            var table = new Dictionary<String, int>();
            foreach (var pair in bufferTable)
            {
                table[pair.Key] = pair.Value.Count;
            }
            return table;
        }

        public void SetTargetID(String targetID)
        {
            if (targetID == null) targetID = "";
            if (targetID != id)
            {
                id = targetID;
                target = -1;
            }
        }

        public String TargetID => id;

        public event EventHandler ExportRequest;

        public void ExportMessages(String filePath)
        {
            var stream = File.Create(filePath);
            var writer = new StreamWriter(stream, Encoding.UTF8);

            if (bufferTable.ContainsKey(id))
            {
                foreach (var row in bufferTable[id])
                {
                    writer.WriteLine(row);
                }
            }

            writer.Close();
            stream.Close();
        }

        private void doPaint(SKCanvas c)
        {
            c.Clear(SKColors.Gray);

            if (Bounds.Width < 10 || Bounds.Height < 10) return;

            int rowHeight = 16;
            int rowCount = ((int)Bounds.Height - 4) / rowHeight;

            List<String> msgs = null;
            int beginRow = 0;

            if (!bufferTable.ContainsKey(id)) return;

            var buffer = bufferTable[id];
            if (buffer.Count == 0) return;

            if (target < rowCount) target = rowCount - 1;
            if (autoScroll || target >= buffer.Count) target = buffer.Count - 1;

            beginRow = Math.Max(0, target - rowCount + 1);
            msgs = buffer.GetRange(beginRow, target - beginRow + 1);

            if (msgs == null || msgs.Count == 0) return;

            var font = c.GetDefaultFont(0.9f);
            for (int i = 0; i < msgs.Count; i++)
            {
                c.DrawString(msgs[i], font, SKColors.WhiteSmoke, AlignmentX.Left, AlignmentY.Top, 4, 4 + i * rowHeight);
            }

            var rectBegin = (float)beginRow / buffer.Count * ((float)Bounds.Height - 2);
            var rectSize = (float)msgs.Count / buffer.Count * ((float)Bounds.Height - 2) + 2;

            c.DrawRect((float)Bounds.Width - 8, rectBegin, 8, rectSize, new SKPaint { Color = SKColors.WhiteSmoke });
        }

        private Dictionary<String, List<String>> bufferTable = new Dictionary<String, List<String>>();
        private String id = "";
        private int target = -1;
        private bool autoScroll = true;
        private LanguageSwitch language;
    }
}